#pragma once


BEGIN_NAMESPACE_OXGE
template <typename  T >
class MATHLIB_TRANSFER Vector2T
{
public:
	typedef T ValueType;
	typedef Vector2T<T> VectorType;

	Vector2T(){  }
	Vector2T(T x, T y){ Set(x,y); }
	Vector2T(const T* cv){ Set(cv); }

	inline VectorType& Set(T ax, T ay){ x = ax; y = ay; return *this; }
	inline VectorType& Set(const T* cv){ memcpy(c_v, cv, sizeof(T)*NLen);  return *this; }

	VectorType& operator *= (const T& dScal ){ x*=dScal; y*=dScal;  return *this;}	
	VectorType& operator += (const VectorType& vR ){ x+=vR.x; y+=vR.y; return *this; }
	VectorType& operator -= (const VectorType& vR ){ x-=vR.x; y-=vR.y; return *this; }

	
	VectorType operator + (const VectorType& vR)const { return VectorType(x+vR.x,y+vR.y); }
	VectorType operator - (const VectorType& vR)const { return VectorType(x-vR.x,y-vR.y); }
	VectorType operator * (const T& rVal )const { return VectorType(x*rVal,y*rVal); } 
	friend VectorType operator *(const T& lVal, const VectorType& rVec){	return rVec * lVal; }

	//
	//T& operator[](size_t idx){ 
	//	assert(idx < NLen);
	//	return c_v[idx];
	//}
	////
	//const T& operator[](size_t idx)const{ 
	//	assert(idx < NLen);
	//	return c_v[idx];
	//}

	inline operator ValueType*() { return c_v; }	
	inline operator const ValueType*()const { return c_v; }

	//dot function
	ValueType dot(const VectorType& vectR)const{ return x * vectR.x + y * vectR.y; }

	//cross 
	VectorType cross()const{ return VectorType(-y,x); }	

	//normalize
	inline VectorType& Normalize(){	return  (*this)*=(ValueType(1)/Length()); }

	//square of len
	inline ValueType SquareLength()const{ return x*x+y*y; }

	//length
	inline ValueType Length()const{	return sqrt(SquareLength()); }
	//
	inline VectorType& SetLength(const T& len){	return (*this)*=(len/Length());	}
	//
	inline VectorType GetNormVector()const{ 
		VectorType vec = *this;
		return vec.Normalize();
	}


	//
	static void UnitTest();


public:
	const static size_t NLen = 2;

	union{
		struct{
			T x,y;
		};
		T c_v[NLen];
	};

	static const VectorType ZERO;
	static const VectorType UNIT_X;
	static const VectorType UNIT_Y;
	static const VectorType UNIT_SCALE;
};




//Global I/O
template<typename T>
std::ostream& operator<<(std::ostream& os, Vector2T<T> vec);

template<typename T>
std::istream& operator>>(std::istream& is, Vector2T<T>& vec);


END_NAMESPACE_OXGE